package com.opencee.boot.autoconfigure.web;

import com.opencee.common.exception.DefaultAccessDeniedHandler;
import com.opencee.common.exception.DefaultAuthenticationEntryPoint;
import com.opencee.common.security.SecurityProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;

/**
 * 默认安全配置
 * 多个WebSecurityConfigurerAdapter
 *
 * @author yadu
 */
@ConditionalOnWebApplication
@Configuration
@Order(200)
@Slf4j
@EnableConfigurationProperties(value = {SecurityProperties.class})
public class DefaultWebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private SecurityProperties properties;

    public DefaultWebSecurityConfiguration() {
        log.info("默认WebSecurity配置@Order(200):如需创建多个WebSecurityConfigurerAdapter,设置小于@Order(200)");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers(
                "/favicon.ico",
                "/error",
                "/static/**",
                "/v2/api-docs/**",
                "/swagger-resources/**",
                "/webjars/**"
        );
    }

    /**
     * 默认安全配置
     *
     * @param http
     * @throws Exception
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        if (properties.isEnable()) {
            String[] permitAll = properties.getPermitAll().toArray(new String[properties.getPermitAll().size()]);
            http.authorizeRequests()
                    .antMatchers(permitAll).permitAll()
                    .anyRequest().authenticated();
        }
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                //为了统一异常处理。每个资源服务器都应该加上。
                .exceptionHandling()
                .accessDeniedHandler(new DefaultAccessDeniedHandler())
                .authenticationEntryPoint(new DefaultAuthenticationEntryPoint())
                .and()
                .csrf().disable();
    }

    /**
     * 认证过滤器
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean bearerTokenFilter(SecurityProperties securityProperties) throws Exception {
        JWTTokenFilter filter = new JWTTokenFilter(securityProperties);
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(filter);
        filterRegistrationBean.setOrder(SecurityWebFiltersOrder.AUTHENTICATION.getOrder() + 2);
        log.info("Bearer token 过滤器[{}]", filter);
        return filterRegistrationBean;
    }
}
